const app = require('j7/app');
const utils = require('j7/utils');
const bcutils = require('j7/bcutils');
const bcconst = require('common/bcconst');
const metaFactory = require('../metadata/factory');
const serviceFactory = require('../services/factory');

async function activate721Nft(session) {
  try {
    const account = bcutils.toNormalAddress(session.request('account'));
    const netId = session.request('net_id');
    const tokenId = session.request('token_id');
    const tokenType = session.request('token_type');
    const itemUniId = session.request('item_uniid');
    const itemId = session.request('item_id');
    const bc = serviceFactory.create('BlockChain');
    const isMint = session.request('is_mint') ? true : false;
    {
      const ret = await bc.init(netId);
      if (!ret) {
        session.rspErr(500, 'net_id error');
        return;
      }
    }
    {
      if (!bc.isValidAddress(account)) {
        session.rspErr(500, 'account error');
        return;
      }
    }

    const nftAddress = bc.getNftAddress(tokenType);
    const userAddress = bc.getUserAddress();
    const thisContractAddress = bc.getContractAddressByName('NFTLock');
    const instance = bc.getInstanceByName('NFTLock');

    const transModel = session.createModel('Transaction');
    const usedTokenIdModel = session.createModel('UsedTokenId');

    {
      const itemMeta = metaFactory.getMetaByKey('Item', itemId);
      if (!itemMeta) {
        session.rspErr(101, 'item_id param error');
        return;
      }
      if (tokenType == bcconst.BC_NFT_NORMAL_HERO) {
        if (itemMeta.getNftType() != bcconst.BC_NFT_HERO) {
          session.rspErr(101, 'item_id param error');
          return;
        }
      } else {
        if (itemMeta.getNftType() != tokenType) {
          session.rspErr(101, 'item_id param error');
          return;
        }
      }
      if (!(itemMeta.getNftType() == bcconst.BC_NFT_HERO ||
            itemMeta.getNftType() == bcconst.BC_NFT_GOLD_BULLION)) {
        session.rspErr(101, 'token_type param error');
        return;
      }
      if (itemMeta.getNftType() == bcconst.BC_NFT_GOLD_BULLION && !isMint) {
        session.rspErr(101, 'gold bullion only mint');
        return;
      }
    }
    {
      if (!nftAddress) {
        session.rspErr(101, 'token_type param error2');
        return;
      }
    }

    const {err, seqId} = await transModel.add(account, session.requestToJson(), netId);
    if (err) {
      console.log(err);
      session.rspErr(500, 'server internal error');
      return;
    }

    const nowTime = utils.getUtcTime();
    const transId = bcutils.genTransId
    (
      bcconst.BC_FUNC_COMMON,
      nowTime,
      seqId,
      [
        itemUniId,
        itemId
      ]
    );
    await transModel.update
    (
      seqId,
      [
        ['trans_id', transId]
      ]);
    const nonce = transId;
    const nftList = [
      [
        tokenId,
        account,
        isMint
      ]
    ];
    const nftListArr = [];
    nftList.forEach((item) => {
      nftListArr.push(item[0].toString());
      nftListArr.push(account);
      if (isMint) {
        nftListArr.push('0x01');
      } else {
        nftListArr.push('0x00');
      }
    });
    const signature = await bc.soliditySha3Sign(
      account,
      nftAddress,
      thisContractAddress,
      netId,
      nowTime,
      nonce,
      ...nftListArr,
    );
    console.log(
      account,
      nftAddress,
      thisContractAddress,
      netId,
      nowTime,
      nonce,
      nftListArr,
      signature
    );

    let data = instance.methods.unlockOrMint
    (
      nftAddress,
      nftList,
      nowTime,
      nonce,
      signature).encodeABI();

    session.rspData({
      'trans_id' : transId,
      'trans_req': {
        'to': thisContractAddress,
        'data': data
      }
    });
  } catch (e) {
    session.rspErr(1, 1);
    utils.safeDumpErrStack(e);
    console.log(e);
  }
}

function init() {
  app.registerHandler('BcService', 'activate721Nft', activate721Nft);
}

exports.init = init;
